package com.googlecode.quillen.domain;

import org.apache.commons.lang.StringUtils;

import java.util.*;
import java.io.Serializable;

/**
 * Created by IntelliJ IDEA.
 * User: greg
 * Date: Dec 8, 2008
 * Time: 9:50:01 AM
 */
public class Attributes implements Serializable
{
    private Map<String, Set<String>> multimap = new HashMap<String, Set<String>>();
    private Set<String> replace;
    private Map<String, Integer> priority = new HashMap<String, Integer>();

    public Set<String> get(String key)
    {
        return multimap.get(key);
    }

    public String getSingle(String key)
    {
        Set<String> vals = get(key);
        if (vals != null && !vals.isEmpty())
        {
            return vals.iterator().next();
        }
        else
        {
            return null;
        }
    }

    public void addReplace(String... keys)
    {
        addReplace(Arrays.asList(keys));
    }

    public void addReplace(Collection<String> keys)
    {
        if (replace == null)
        {
            replace = new HashSet<String>();
        }

        replace.addAll(keys);
    }

    public void removeReplace(String... keys)
    {
        removeReplace(Arrays.asList(keys));
    }

    public void removeReplace(Collection<String> keys)
    {
        if (replace != null)
        {
            replace.removeAll(keys);
        }
    }

    public boolean isReplace(String key)
    {
        return replace != null && replace.contains(key);
    }

    public Set<String> getReplaces()
    {
        return replace;
    }

    public void setPriority(String key, int level)
    {
        if (priority == null)
        {
            priority = new HashMap<String, Integer>();
        }

        priority.put(key, level);
    }

    public int getPriority(String key)
    {
        Integer result = null;

        if (priority != null)
        {
            result = priority.get(key);
        }

        if (result == null)
        {
            result = 0;
        }

        return result;
    }

    public void add(String key, String value)
    {
        Set<String> vals = multimap.get(key);

        if (vals == null)
        {
            vals = new HashSet<String>();
            multimap.put(key, vals);
        }

        vals.add(value);
    }

    public void add(String key, Collection<String> values)
    {
        if (values != null && !values.isEmpty())
        {
            Set<String> vals = multimap.get(key);

            if (vals == null)
            {
                vals = new HashSet<String>();
                multimap.put(key, vals);
            }

            vals.addAll(values);
        }
    }

    public String remove(String key, String val)
    {
        Set<String> vals = multimap.get(key);

        if (vals != null)
        {
            vals.remove(val);

            if (vals.isEmpty())
            {
                multimap.remove(key);
            }

            return val;
        }

        return null;
    }

    public Set<String> remove(String key)
    {
        return multimap.remove(key);
    }

    public String removeSingle(String key)
    {
        Set<String> removed = remove(key);

        if (removed != null && !removed.isEmpty())
        {
            return removed.iterator().next();
        }
        else
        {
            return null;
        }
    }

    public Map<String, Set<String>> removeWithPrefix(String keyPrefix)
    {
        Map<String, Set<String>> result = new HashMap<String, Set<String>>();

        for (String key : new ArrayList<String>(multimap.keySet()))
        {
            if (StringUtils.startsWith(key, keyPrefix))
            {
                result.put(key, remove(key));
            }
        }

        return result;
    }

    public Set<String> getKeys()
    {
        return multimap.keySet();
    }

    public boolean isEmpty()
    {
        return multimap.isEmpty();
    }

    public int size()
    {
        int size = 0;

        for (String k : multimap.keySet())
        {
            size += multimap.get(k).size();
        }

        return size;
    }

    public boolean containsKey(String key)
    {
        return multimap.containsKey(key);
    }

    public boolean contains(String key, String val)
    {
        Set<String> vals = multimap.get(key);
        
        return vals != null && vals.contains(val);
    }

    public void merge(Attributes attrs)
    {
        if (attrs != null)
        {
            for (String key : attrs.getKeys())
            {
                add(key, attrs.get(key));
            }
        }
    }

    public Attributes copy()
    {
        Attributes result = new Attributes();

        for (String key : getKeys())
        {
            result.add(key, get(key));
        }

        if (replace != null)
        {
            result.replace = new HashSet<String>(replace);
        }

        if (priority != null)
        {
            result.priority = new HashMap<String, Integer>(priority);
        }

        return result;
    }

    public boolean equals(Attributes other)
    {
        return other != null && multimap.equals(other.multimap);
    }

    public int hashCode()
    {
        return multimap.hashCode();
    }
}
